redis配置 && memcache配置 及对比

Redis

1.配置Jedis参数

redis.clients.jedis.JedisPoolConfig

<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
        <!-- 最大能够保持idel状态的对象数  -->
        <property name="maxIdle" value="${jedis.maxIdle}" /> 
        <!-- 最大分配的对象数  高版本中用来替换maxWait参数 -->
        <property name="maxWaitMillis" value="${jedis.maxWait}" />
        <!-- 最大分配的对象数 -->
        <property name="maxTotal" value="${jedis.maxTotal}" />
        <!-- 当调用borrowObject获取jedis实例方法时,是否进行有效性检查(ping) -->
        <property name="testOnBorrow" value="true" /> 

        <!------------------------------ 通常配置以上参数,以下参数可选 ---------------------------------->
        <!-- 最大能获得jedis实例的个数,高版本中删除 -->
        <property name="maxActive" value="${jedis.maxActive}"/> 
       <!-- pool中的jedis实例被用完时的策略  
                        WHEN_EXHAUSTED_FAIL      表示无jedis实例时,直接抛出NoSuchElementException;  
                        WHEN_EXHAUSTED_BLOCK      表示阻塞住,超时抛出JedisConnectionException;
                        WHEN_EXHAUSTED_GROW    表示自动增长,新建一个jedis实例,不受maxTotal限制 -->
        <property name="whenExhaustedAction" value="${jedis.whenExhaustedAction}">
        <!-- borrowObject返回jedis实例时采用FIFO策略还是LIFO策略  默认为true(LIFO策略),false为FIFO  -->
        <property name="lifo" value="${jedis.lifo}">
</bean>

2.配置redis池

redis.clients.jedis.JedisPool

<bean id="jedisPool0" class="redis.clients.jedis.JedisPool">
        <!-- jedis配置  -->
        <constructor-arg name="poolConfig" ref="jedisPoolConfig" />
        <!-- jedis服务器地址 -->
        <constructor-arg name="host" value="${jedis.host}" />
        <!-- jedis服务器端口 -->
        <constructor-arg name="port" value="${jedis.port}" type="int" />
        <!-- 指定在空闲多少秒后断开连接 -->
        <constructor-arg name="timeout" value="${jedis.timeout}" type="int" />
        <!-- jedis服务器密码 -->
        <constructor-arg name="password" value="#{'${jedis.pwd}'!=''?'${jedis.pwd}':null}" />
        <!-- jedis数据库index -->
        <constructor-arg name="database" value="${jedis.db.index0}" type="int" />
</bean>
<!-- 配置多个redis池 -->   
<bean id="jedisPool1" class="redis.clients.jedis.JedisPool">
        <constructor-arg name="poolConfig" ref="jedisPoolConfig" />
        <constructor-arg name="host" value="${jedis.host}" />
        <constructor-arg name="port" value="${jedis.port}" type="int" />
        <constructor-arg name="timeout" value="${jedis.timeout}" type="int" />
        <constructor-arg name="password" value="#{'${jedis.pwd}'!=''?'${jedis.pwd}':null}" />
        <constructor-arg name="database" value="${jedis.db.index1}" type="int" />
</bean>

3.配置工具map

<bean id="jedisPoolsMap" class="java.util.HashMap">
        <constructor-arg>
            <map>
                <entry key="${jedis.db.index0}" value-ref="jedisPool0"/>
                <entry key="${jedis.db.index1}" value-ref="jedisPool1"/>
            </map>
        </constructor-arg>
</bean>

4.jedis的使用

文末会附上jedis工具类的java代码

5.服务器查看redis的键值

ps -ef | grep redis-server   #查看redis信息
netstat -ano | grep -6379  #按端口查找
redis-cli -h 127.0.0.1 -p 6379 --raw  #登陆redis服务器,-h 主机ip , -p 端口号  , -a  密码   --raw按中文原有方式输出
KEYS  #返回所有关键字
GET key   #根据关键字获取字符串类型的值
HEYS key    #返回哈希表key中所有的域 
HGET key field     #返回哈希表key中给定域的值
HMGET key field[filed....]  #返回哈希表key中给定的多个域的值
DEL key[key...]   #删除给定的一个或多个key
Quit 

*************************************************************华丽的分割线*************************************************************


Memcache

1.配置IO线程池

<bean id="memcacheResource" class="com.whalin.MemCached.SockIOPool"
        factory-method="getInstance" init-method="initialize" destroy-method="shutDown">
     <!-- 构造函数参数 -->
    <constructor-arg><value>memcacheResource</value></constructor-arg>
    <!-- memcache服务器的地址,可以设置多个服务器 -->
    <property name="servers"><list><value>${memcacheURL}</value></list></property>
    <!-- 每个服务器初始连接数 -->
    <property name="initConn"><value>10</value></property>
    <!-- 每个服务器最小连接数 -->
    <property name="minConn"><value>10</value></property>
    <!-- 每个服务器最大连接数 -->
    <property name="maxConn"><value>150</value></property>
    <!-- 每隔5秒维护一次连接数 -->
    <property name="maintSleep"><value>5000</value></property>
    <!-- 最大空闲时间 -->
    <property name="maxIdle"><value>600000</value></property>
    <!-- 禁用nagle算法  -->
    <property name="nagle"><value>false</value></property>
    <!-- TCP连接读取超时   3秒钟 -->
    <property name="socketTO"><value>3000</value></property>
</bean>

2.配置客户端和包装类

<bean id="mccResource" class="com.whalin.MemCached.MemCachedClient">
    <constructor-arg>
        <value>memcacheResource</value>
    </constructor-arg>
</bean>
<!-- 自定义封装的包装类,文末会附上示例代码 -->
<bean id="cacheWrapper" class="com.revo.eeducation.server.memcached.MemCacheWrapper">
    <constructor-arg>
        <ref bean="mccResource" />
    </constructor-arg>
</bean>

3.服务器查看缓存

get key[key...]   #返回储存在键中的值
set key 0 900 9      #设置键值对   key键   flags  一般为0   exptime 缓存时效(秒)bytes 在缓存中存储的字节
memcache    #设置存储的值   必须换行,且长度要跟设置的字节数一致,不然会报错CLIENT_ERROR bad data chunk
replace、append、prepend的语法跟set一致
stats   #统计命令

Redis 和 memcache 比较

内存使用效率:用简单的key-value存储,memcache的效率更好,而如果redis使用Hash结构来存储key-value,则redis的效率要高于memcache
性能方面: 在小数据量存储时,redis要高于memcache;在超过100K的数据中,memcache的性能更优
另外: redis对复杂数据提供的支持更多,而memcache可以设置多个服务器



JedisUtil.java

@Component
public class JedisUtil {
    
    private static final Logger LOGGER = Logger.getLogger(JedisUtil.class);
    
    /**默认数据库*/
    public static final int DB_DEFAULT = 0;
    
    /**数据库缓存*/
    public static final int DB_SQL = 1;
    
    /**jedis连接池对象名前缀*/
    public static final String JEDIS_POOL_PREFIX = "jedisPool";
    
    @Autowired
    private Map<String,JedisPool> jedisPoolsMap;


    /**
     * 获取jedis对象
     * @param database 数据库
     * @return Jedis对象
     */
    private Jedis getJedis(int database){
        
        if(MapUtils.isEmpty(jedisPoolsMap)){
            LOGGER.info("=============================注入连接池jedisPoolsMap失败=========================================");
        }
        return jedisPoolsMap.get(JEDIS_POOL_PREFIX+database).getResource();
    }
    
    
    /**
     * 检测redis是否OK
     * @return ok返回<code>true</code>
     */
    public boolean isOK(){
        Boolean bl = Boolean.FALSE;
        Jedis jedis = getJedis(DB_DEFAULT);
        if(!CommonUtils.isEmpty(jedis)){
            bl = Boolean.TRUE;
        }
        jedis.close();
        return bl;
    }

    /**
     * 设置缓存
     * @param database 数据库
     * @param key 缓存KEY
     * @param value 缓存值
     * @return Status code reply
     */
    public String set(int databse,String key,String value){
        Jedis jedis = getJedis(databse);
        
        String val = jedis.set(key, value);
        jedis.close();
        return val;
    }
    
    
    /**
     * 设置缓存
     * @param key 缓存KEY
     * @param value 缓存值
     * @return Status code reply
     */
    public String set(String key,String value){
        return set(DB_DEFAULT, key, value);
    }
    
    /**
     * 设置缓存
     * @param database 数据库
     * @param key 缓存KEY
     * @param value 缓存值
     * @return Status code reply
     */
    public String set(int databse,String key,Serializable value){
        Jedis jedis = getJedis(databse);
        String val = jedis.set(key.getBytes(), SerializableUtil.toByteArray(value));
        jedis.close();
        return val;
    }
    
    /**
     * 设置缓存
     * @param key 缓存KEY
     * @param value 缓存值
     * @return Status code reply
     */
    public String set(String key,Serializable value){
        return set(DB_DEFAULT, key, value);
    }
    
    /**
     * 设置带有时间长度的缓存
     * @param database 数据库
     * @param key 缓存KEY
     * @param value 缓存值
     * @param time 缓存时间 ,毫秒
     * @return Status code reply
     */
    public String set(int database,String key,String value,long time){
        Jedis jedis = getJedis(database);
        String nxxx = "NX";
        if(jedis.exists(key)){
            nxxx = "XX";
        }
        String val = jedis.set(key, value,nxxx,"PX",time);
        jedis.close();
        return val;
    }
    
    /**
     * 设置带有时间长度的缓存
     * @param key 缓存KEY
     * @param value 缓存值
     * @param time 缓存时间 ,毫秒
     * @return Status code reply
     */
    public String set(String key,String value,long time){
        return set(DB_DEFAULT, key, value, time);
    }
    
    /**
     * 设置带有时间长度的缓存
     * @param database 数据库
     * @param key 缓存KEY
     * @param value 缓存值
     * @param time 缓存时间 ,毫秒
     * @return Status code reply
     */
    public String set(int database,String key,Serializable value,long time){
        Jedis jedis = getJedis(database);
        byte[] byteKey = SerializableUtil.toByteArray(key);
        
        String nxxx = "NX";
        if(jedis.exists(byteKey)){
            nxxx = "XX";
        }
        
        byte[] nxxxByte = nxxx.getBytes();
        byte[] epxxByte = "PX".getBytes();
        
        String val = jedis.set(byteKey, SerializableUtil.toByteArray(value),nxxxByte,epxxByte,time);
        jedis.close();
        return val;
    }
    
    /**
     * 设置带有时间长度的缓存
     * @param key 缓存KEY
     * @param value 缓存值
     * @param time 缓存时间 ,毫秒
     * @return Status code reply
     */
    public String set(String key,Serializable value,long time){
        return set(DB_DEFAULT, key, value, time);
    }
    
    /**
     * 检查redis中是否包含key
     * @param database 数据库
     * @param key redis key
     * @return true if key is exists
     */
    public boolean containsKey(int database,String key){
        Jedis jedis = getJedis(database);
        boolean result =  jedis.exists(key);
        jedis.close();
        return result;
    }

    /**
     * 检查redis中是否包含key
     * @param key redis key
     * @return true if key is exists
     */
    public boolean containsKey(String key){
        return containsKey(DB_DEFAULT, key);
    }
    
    /**
     * 调用Redis的LPUSH命令
     * @param database 数据库
     * @param key redis key
     * @param val redis value
     * @return true if key is exists
     */
    public Long lpush(int database,String key,String... val){
        Long ret = -1L;
        Jedis jedis = getJedis(database);
        ret = jedis.lpush(key, val);
        jedis.close();
        return ret;
    }
    
    /**
     * 调用Redis的LPUSH命令
     * @param key redis key
     * @param val redis value
     * @return true if key is exists
     */
    public Long lpush(String key,String... val){
        return lpush(DB_DEFAULT, key, val);
    }
    
    /**
     * 调用Redis的hmset 将map保存到redis缓存中
     * @param database 数据库
     * @param key
     * @param map
     */
    public void hmset(int database,String key,Map<String, String> map){
        Jedis jedis = getJedis(database);
        jedis.hmset(key, map);
        jedis.close();
    }
    
    /**
     * 调用Redis的hmset 将map保存到redis缓存中
     * @param key
     * @param map
     */
    public void hmset(String key,Map<String, String> map){
        hmset(DB_DEFAULT, key, map);
    }
    
    /**
     * 调用Redis的hmget 获取对应key保存map中存储的fields对应的数据
     * @param key
     * @param fields
     * @return
     */
    public List<String> hmget(int database,String key,String... fields){
        Jedis jedis = getJedis(database);
        List<String> list = jedis.hmget(key, fields);
        jedis.close();
        return list;
    }
    
    /**
     * 调用Redis的hmget 获取对应key保存map中存储的fields对应的数据
     * @param key
     * @param fields
     * @return
     */
    public List<String> hmget(String key,String... fields){
        return hmget(DB_DEFAULT, key, fields);
    }
    
    /**
     * 调用Redis的hmget 获取对应key保存map中存储的fields对应的数据
     * @param database 数据库
     * @param key 缓存的KEY
     * @param cls 需要转换的对象
     * @param fields map的key
     * @return
     */
    public <T> List<T> hmget(int database,String key,Class<T> cls,String... fields){
        Jedis jedis = getJedis(database);
        List<String> list = jedis.hmget(key, fields);
        if(CollectionUtils.isNotEmpty(list) && !list.contains(null)){
            String retStr = Joiner.on(",").join(list);
            retStr = StringUtils.appendIfMissing(retStr, "]", "]");
            retStr = StringUtils.prependIfMissing(retStr, "[", "[");
            
            jedis.close();
            return JSON.parseArray(retStr, cls);
        }
        jedis.close();
        return null;
    }

    /**
     * 调用Redis的hmget 获取对应key保存map中存储的fields对应的数据
     * @param key 缓存的KEY
     * @param cls 需要转换的对象
     * @param fields map的key
     * @return
     */
    public  <T> List<T> hmget(String key,Class<T> cls,String... fields){
        return hmget(DB_DEFAULT, key, cls, fields);
    }
    
    /**
     * 调用Redis的hmget 获取对应key保存map中存储的fields对应的数据
     * @param database 数据库
     * @param key 缓存的KEY
     * @param type 需要转换的对象
     * @param fields map的key
     * @return
     */
    public  <T> List<T> hmget(int database,String key,Type type,String... fields){
        Jedis jedis = getJedis(database);
        List<String> list = jedis.hmget(key, fields);
        if(CollectionUtils.isNotEmpty(list) && !list.contains(null)){
            String retStr = Joiner.on(",").join(list);
            retStr = StringUtils.appendIfMissing(retStr, "]", "]");
            retStr = StringUtils.prependIfMissing(retStr, "[", "[");
            
            jedis.close();
            return JSON.parseObject(retStr, type);
        }
        jedis.close();
        return null;
    }
    
    /**
     * 调用Redis的hmget 获取对应key保存map中存储的fields对应的数据
     * @param key 缓存的KEY
     * @param type 需要转换的对象
     * @param fields map的key
     * @return
     */
    public  <T> List<T> hmget(String key,Type type,String... fields){
        return hmget(DB_DEFAULT, key, type, fields);
    }
    
    /**
     * 调用Redis的hmget 获取全部数据
     * @param database 数据库
     * @param key
     * @return
     */
    public  Map<String,String> hgetAll(int dababase,String key){
        Jedis jedis = getJedis(dababase);
        Map<String,String> map = jedis.hgetAll(key);
        jedis.close();
        return map;
    }
    
    /**
     * 调用Redis的hmget 获取全部数据
     * @param key
     * @return
     */
    public  Map<String,String> hgetAll(String key){
        return hgetAll(DB_DEFAULT, key);
    }
    
    /**
     * 调用Redis的hmget 获取全部value数据
     * @param key
     * @return
     */
    public  List<Object> hgetAllValue2Object(int database,String key){
        Map<String, String> map = hgetAll(database,key);
        List<Object> valList = new ArrayList<>();
        if(map != null){
            for (Iterator<String> iterator = map.values().iterator(); iterator.hasNext();) {
                String val = iterator.next();
                if(JsonUtils.isJSONArray(val)){
                    JSONArray jsonArray = JSON.parseArray(val);
                    if(!jsonArray.isEmpty()){
                        for (Object json : jsonArray) {
                            valList.add(json);
                        }
                    }
                }else if(JsonUtils.isJSONObject(val)){
                    valList.add(JSON.parse(val));
                }else{
                    valList.add(val);
                }
            }
        }
        
        return valList;
    }
    
    /**
     * 调用Redis的hmget 获取全部value数据
     * @param key
     * @return
     */
    public  List<Object> hgetAllValue2Object(String key){
        return hgetAllValue2Object(DB_DEFAULT, key);
    }
    
    /**
     * 调用Redis的hmget 获取全部value数据
     * @param key
     * @return
     */
    public  String hgetAllValue2Str(String key){
        List<Object> valList = hgetAllValue2Object(key);
        return CollectionUtils.isEmpty(valList) ? StringUtils.EMPTY : JSON.toJSONString(valList);
    }
    
    /**
     * 调用Redis的hmget 获取全部value数据,并转换为对象
     * @param key
     * @param cls
     * @return
     */
    public  <T> List<T> hgetAllValue(String key,Class<T> cls){
        List<Object> valList = hgetAllValue2Object(key);
        return JSON.parseArray(JSON.toJSONString(valList),cls);
    }
    
    /**
     * 调用Redis的hmget 获取全部value数据,并转换为对象
     * @param key
     * @param cls
     * @return
     */
    public  <T> T hgetAllValue(String key,Type type){
        List<Object> valList = hgetAllValue2Object(key);
        return JSON.parseObject(JSON.toJSONString(valList),type);
    }
    
    /**
     * 调用Redis的hmget 获取全部key数据
     * @param key
     * @return
     */
    public  List<String> hgetAllKey2Str(String key){
        Map<String, String> map = hgetAll(key);
        
        List<String> ret = new ArrayList<>();
        ret.addAll(map.keySet());
        return ret;
    }
    
    /**
     * 调用Redis的hmget 获取对应key保存map中存储的fields对应的数据
     * @param database 数据库
     * @param key
     * @param fields
     * @return
     */
    public  String hmget4Single(int database,String key,String field){
        String ret = StringUtils.EMPTY;
        Jedis jedis = getJedis(database);
        List<String> list = jedis.hmget(key, field);
        if(CollectionUtils.isNotEmpty(list)){
            ret = list.get(0);
        }
        jedis.close();
        return ret;
    }
    
    /**
     * 调用Redis的hmget 获取对应key保存map中存储的fields对应的数据
     * @param key
     * @param fields
     * @return
     */
    public  String hmget4Single(String key,String field){
        return hmget4Single(DB_DEFAULT, key, field);
    }
    
    /**
     * 调用Redis的hmget 获取对应key保存map中存储的fields对应的数据
     * @param database 数据库
     * @param key
     * @param fields
     * @param cls 需要转换的对象
     * @return
     */
    public  <T> T hmget4Single(int database,String key,String field,Class<T> cls){
        String ret = StringUtils.EMPTY;
        Jedis jedis = getJedis(database);
        List<String> list = jedis.hmget(key, field);
        if(CollectionUtils.isNotEmpty(list)){
            ret = list.get(0);
        }
        jedis.close();
        return StringUtils.isNotEmpty(ret) ? JSON.parseObject(ret, cls) : null;
    }
    
    /**
     * 调用Redis的hmget 获取对应key保存map中存储的fields对应的数据
     * @param key
     * @param fields
     * @param cls 需要转换的对象
     * @return
     */
    public  <T> T hmget4Single(String key,String field,Class<T> cls){
        return hmget4Single(DB_DEFAULT, key, field, cls);
    }
    
    /**
     * 调用Redis的HSET命令-散列
     * @param database 数据库
     * @param key redis key
     * @param val redis value
     * @return true if key is exists
     */
    public  Long hset(int database,String key,String field,String value){
        Long ret = -1L;
        Jedis jedis = getJedis(database);
        ret = jedis.hset(key, field, value);
        jedis.close();
        return ret;
    }
    
    /**
     * 调用Redis的HSET命令-散列
     * @param key redis key
     * @param val redis value
     * @return true if key is exists
     */
    public  Long hset(String key,String field,String value){
        return hset(DB_DEFAULT, key, field, value);
    }

    /**
     * 根据key前缀获取所有匹配的value
     * @param database 数据库
     * @param prefixKey key 前缀
     * @return List
     */
    public  List<String> getAllElementByPrefixKey(int database,String prefixKey){
        Jedis jedis = getJedis(database);
        List<String> result = new ArrayList<>();
        Set<String> values = jedis.keys(prefixKey + "*");
        for (String value : values){
            result.add(value);
        }
        jedis.close();
        return result;
    }
    
    /**
     * 根据key前缀获取所有匹配的value
     * @param prefixKey key 前缀
     * @return List
     */
    public  List<String> getAllElementByPrefixKey(String prefixKey){
        return getAllElementByPrefixKey(DB_DEFAULT, prefixKey);
    }

    /**
     * 根据KEY获取缓存数据
     * @param database 数据库
     * @param key 缓存KEY
     * @return 获取的缓存值
     */
    public  String get(int database,String key){
        Jedis jedis = getJedis(database);
        String val = jedis.get(key);
        jedis.close();
        return val;
    }
    
    /**
     * 根据KEY获取缓存数据
     * @param key 缓存KEY
     * @return 获取的缓存值
     */
    public String get(String key){
        return get(DB_DEFAULT, key);
    }
    
    /**
     * 根据KEY获取缓存数据
     * @param key 缓存KEY
     * @return 获取的缓存值
     */
    @SuppressWarnings("unchecked")
    public  <T> T getSerializable(int database,String key){
        Jedis jedis = getJedis(database);
        byte[] byteKey = SerializableUtil.toByteArray(key);
        
        if(!jedis.exists(byteKey)){
            jedis.close();
            return null;
        }
        Serializable val = SerializableUtil.toObject(jedis.get(byteKey));
        jedis.close();
        return (T) val;
    }
    
    /**
     * 根据KEY获取缓存数据
     * @param key 缓存KEY
     * @return 获取的缓存值
     */
    public  <T> T getSerializable(String key){
        return getSerializable(DB_DEFAULT, key);
    }
    
    /**
     * 根据KEY获取缓存数据对象
     * @param key 缓存KEY
     * @param clasz 需要转换的对象
     * @return 从缓存中获取的对象
     */
    public  <T> T get(int database,String key,Class<T> clasz){
        Jedis jedis = getJedis(database);
        String val = jedis.get(key);
        jedis.close();
        return StringUtils.isEmpty(val) ? null : JSON.parseObject(val, clasz);
    }
    
    /**
     * 根据KEY获取缓存数据对象
     * @param key 缓存KEY
     * @param clasz 需要转换的对象
     * @return 从缓存中获取的对象
     */
    public  <T> T get(String key,Class<T> clasz){
        return get(DB_DEFAULT, key, clasz);
    }
    
    /**
     * 根据KEY获取缓存数据并转换成List
     * @param key
     * @return string集合
     */
    public  List<String> getRedisList(String key){
        String value = get(key);
        if(StringUtils.isEmpty(value)){
            return new ArrayList<>();
        }
        @SuppressWarnings("unchecked")
        List<String> list = JSON.parseObject(value, List.class);
        return list;
    }
    
    /**
     * 根据key删除client的缓存
     * @param database 数据库
     * @param key
     */
    public  void remove(int database,String key){
        Jedis jedis = getJedis(database);
        if(jedis.exists(key)){
            Long del = jedis.del(key);
        }
        jedis.close();
    }
    
    /**
     * 根据key删除client的缓存
     * @param key
     */
    public  void remove(String key){
        remove(DB_DEFAULT, key);
    }
    
    /**
     * 根据前缀删除缓存
     * @param database 数据库
     * @param regex 正则字符串
     */
    public  void removePattern(int database,String regex){
        Jedis jedis = getJedis(database);
        Set<String> keys = jedis.keys(regex);
        if(!CommonUtils.isEmpty(keys)){
            jedis.del((String[])keys.toArray(new String[keys.size()])); 
        }
        jedis.close();
    }
    
    /**
     * 根据前缀删除缓存
     * @param regex 正则字符串
     */
    public  void removePattern(String regex){
        removePattern(DB_DEFAULT, regex);
    }
    
    /**
     * 根据前缀删除缓存
     * @param regex 正则字符串
     */
    public  void removeSerializePattern(int database,String regex){
        Jedis jedis = getJedis(database);
        Set<byte[]> keys = jedis.keys(regex.getBytes());
        if(!CommonUtils.isEmpty(keys)){
            byte[][] keyByteArray = new byte[keys.size()][];
            
            int i = 0;
            for (Iterator<byte[]> iterator = keys.iterator(); iterator.hasNext();) {
                byte[] bs = (byte[]) iterator.next();
                keyByteArray[i++] = bs;
            }
            
            jedis.del(keyByteArray);    
        }
        jedis.close();
    }
    
    /**
     * 根据前缀删除缓存
     * @param regex 正则字符串
     */
    public  void removeSerializePattern(String regex){
        removeSerializePattern(DB_DEFAULT, regex);
    }
    
    /**
     * 向redis中添加字符串集合
     * @param database 数据库
     * @param key redis中key
     * @param valueList 字符串集合
     */
    public  void addListElement(int database,String key,List<String> valueList){
        if (CollectionUtils.isEmpty(valueList)){
            return;
        }
        Jedis jedis = getJedis(database);
        jedis.rpush(key, valueList.toArray(new String[valueList.size()]));
        jedis.close();
    }
    
    /**
     * 向redis中添加字符串集合
     * @param key redis中key
     * @param valueList 字符串集合
     */
    public  void addListElement(String key,List<String> valueList){
        addListElement(DB_DEFAULT, key, valueList);
    }
    
    /**
     * 向redis中添加字符串
     * @param database 数据库
     * @param key redis中key
     * @param strings 字符串
     */
    public  void addStrElement(int database,String key, String... strings) {
        if (strings.length <= 0) {
            return;
        }
        Jedis jedis = getJedis(database);
        jedis.rpush(key, strings);
        jedis.close();
    }
    
    /**
     * 向redis中添加字符串
     * @param key redis中key
     * @param strings 字符串
     */
    public  void addStrElement(String key, String... strings) {
        addStrElement(DB_DEFAULT, key, strings);
    }
    
    /**
     * 根据key获取list所有元素
     * @param key redis中key
     * @return List
     */
    public  List<String> getListByKey(int database,String key){
        Jedis jedis = getJedis(database);
        List<String> result = jedis.lrange(key, 0l, jedis.llen(key) - 1);
        jedis.close();
        return result;
    }

    /**
     * 根据key获取list所有元素
     * @param key redis中key
     * @return List
     */
    public  List<String> getListByKey(String key){
        return getListByKey(DB_DEFAULT, key);
    }
    
    /**
     * 取出并删除名称为key的list首元素
     * @param key redis中key
     * @return list中首元素
     */
    public  String removeListElement(int database,String key){
        Jedis jedis = getJedis(database);
        String result = jedis.lpop(key);
        jedis.close();
        return result;
    }

    /**
     * 取出并删除名称为key的list首元素
     * @param key redis中key
     * @return list中首元素
     */
    public  String removeListElement(String key){
        return removeListElement(DB_DEFAULT, key);
    }

    /**
     * 获取名称为key的list size
     * @param database 数据库
     * @param key redis中key
     * @return size
     */
    public  long getListSizeByKey(int database,String key){
        Jedis jedis = getJedis(database);
        long size = jedis.llen(key);
        jedis.close();
        return size;
    }
    /**
     * 获取名称为key的list size
     * @param key redis中key
     * @return size
     */
    public  long getListSizeByKey(String key){
        return getListSizeByKey(DB_DEFAULT, key);
    }

    /**
     * 获取redis中名称key的list中count个元素并删除(从头至尾删除)
     * @param database 数据库
     * @param key redis中key
     * @param count 需删除的元素个数
     * @return list,删除的元素集合,count必须大于零小于等于list size,否则返回empty list
     */
    public  List<String> removeList(int database,String key,int count){
        List<String> result = new ArrayList<>();
        if (count <= 0){
            return result;
        }
        Jedis jedis = getJedis(database);
        long listSize = jedis.llen(key);
        if (count > listSize){
            count = (int)listSize;
        }
        for (int x = 0,i = count; x < i; x++){
            result.add(jedis.lpop(key));
        }
        jedis.close();
        return result;
    }
    
    /**
     * 获取redis中名称key的list中count个元素并删除(从头至尾删除)
     * @param key redis中key
     * @param count 需删除的元素个数
     * @return list,删除的元素集合,count必须大于零小于等于list size,否则返回empty list
     */
    public  List<String> removeList(String key,int count){
        return removeList(DB_DEFAULT, key, count);
    }

    /**
     * 获取redis中名称key的MAP中 key为${mapKey}的value值
     * @param jedisKey
     * @param mapKey
     * @return List<String>
     */
    public  List<String> getMapValByKey(int database,String jedisKey, String mapKey) {
        Jedis jedis = getJedis(database);
        List<String> list = jedis.hmget(jedisKey, mapKey);
        jedis.close();
        return list;
    }
    
    /**
     * 获取redis中名称key的MAP中 key为${mapKey}的value值
     * @param jedisKey
     * @param mapKey
     * @return List<String>
     */
    public  List<String> getMapValByKey(String jedisKey, String mapKey) {
        return getMapValByKey(DB_DEFAULT, jedisKey, mapKey);
    }
   
    /**
     * 检查key在redis中是否存在
     * @param key
     * @return 存在返回<code>true</code>,否则返回<code>false</code>
     */
    public  boolean exists(int database,String key) {
        Jedis jedis = getJedis(database);
        Boolean exists = jedis.exists(key);
        jedis.close();

        return exists;
    }
    
    /**
     * 检查key在redis中是否存在
     * @param key
     * @return 存在返回<code>true</code>,否则返回<code>false</code>
     */
    public  boolean exists(String key) {
        return exists(DB_DEFAULT, key);
    }
    
    /**
     * 设置 list
     * @param database 数据库
     * @param <T>
     * @param key
     * @param value
     */
    public  <T> void setList(int database,String key, List<T> list) {
        Jedis jedis = getJedis(database);
        try {
            jedis.set(key.getBytes(), ObjectSerializableUtil.serialize(list));
        } catch (Exception e) {
            LOGGER.error("Set key error : " + e);
        }finally{
            jedis.close();
        }
    }
    
    /**
     * 设置 list
     * @param <T>
     * @param key
     * @param value
     */
    public  <T> void setList(String key, List<T> list) {
        setList(DB_DEFAULT, key, list);
    }

    /**
     * 获取list
     * @param database 数据库
     * @param <T>
     * @param key
     * @return list
     */
    @SuppressWarnings("unchecked")
    public  <T> List<T> getList(int database,String key) {
        if(StringUtils.isEmpty(key)){
            LOGGER.error("jedis-传入的KEY为空");
            return null;
        }
        Jedis jedis = getJedis(database);
        if (jedis == null || !jedis.exists(key.getBytes())) {
            jedis.close();
            return null;
        }
        byte[] in = jedis.get(key.getBytes());
        List<T> list = (List<T>) ObjectSerializableUtil.deserialize(in);
        jedis.close();
        return list;
    }
    
    /**
     * 获取list
     * @param <T>
     * @param key
     * @return list
     */
    public  <T> List<T> getList(String key) {
        return getList(DB_DEFAULT, key);
    }
}

MemCacheWrapper.java


/**
 * 包装 {@link MemCachedClient},集中处理缓存错误不影响业务流程
 * 
 * 
 */
public class MemCacheWrapper
{
    private static ServerLogger logger = new ServerLogger(MemCacheWrapper.class);
    
    private MemCachedClient client;
    
    /**
     * 是否可写(默认为可写)
     */
    private boolean writable = true;
    
    private String[] servers;
    
    public MemCacheWrapper(MemCachedClient client)
    {
        this.client = client;
        try
        {
            com.whalin.MemCached.SockIOPool sockIOPool = BeanHolder.getBean("memcacheResource");
            this.servers = sockIOPool.getServers();
            String localIp = InetAddress.getLocalHost().getHostAddress();
            boolean matched = false;
            for (String server : this.servers)
            {
                //只有添加在里面的ip才会开启可写模式;
                if (server.contains("localhost") || server.contains("127.0.0.1") || server.contains(localIp))
                {
                    matched = true;
                    break;
                }
            }
            this.writable = matched;
        }
        catch (Exception e)
        {
            logger.error("判断memcached是否可写失败!", e);
        }
    }
    
    public <T> Map<String, T> getMulti(Class<T> type, String... keys)
    {
        return getMap(type, keys);
    }
    
    @SuppressWarnings("unchecked")
    private <T> Map<String, T> getMap(Class<T> type, String... keys)
    {
        Map<String, Object> map = client.getMulti(keys);
        if (map == null)
        {
            // 总是返回一个Map防止程序出现空指针异常
            return new HashMap<String, T>();
        }
        Iterator<Entry<String, Object>> it = map.entrySet().iterator();
        while (it.hasNext())// 类型转换检查
        {
            Entry<String, Object> entry = it.next();
            if (entry.getValue() == null)
            {
                continue;
            }
            entry.setValue(castAs(type, entry.getKey(), entry.getValue()));
            if (entry.getValue() == null)
            {
                it.remove();
            }
        }
        return (Map<String, T>)map;
    }
    
    public <T> T get(Class<T> type, String key)
    {
        Object t = client.get(key);
        return castAs(type, key, t);
    }
    
    @SuppressWarnings("unchecked")
    public <T> T[] getMultiArray(Class<T> type, String... keys)
    {
        Object[] values = client.getMultiArray(keys);
        if (values == null)
        {
            return (T[])Array.newInstance(type, 0);
        }
        T[] arr = (T[])Array.newInstance(type, values.length);
        for (int i = 0; i < values.length; i++)
        {
            arr[i] = castAs(type, null, values[i]);
        }
        return arr;
    }
    
    /**
     * 增加一个指定键的计数器+1
     * 
     * @param key
     * @return
     */
    public long incr(String key)
    {
        return client.incr(key);
    }
    
    /**
     * 增加一个指定键的计数器+value
     * 
     * @param key
     * @param value
     * @return
     */
    public long incr(String key, long value)
    {
        return client.incr(key, value);
    }
    
    public long decr(String key)
    {
        return client.decr(key);
    }
    
    public long decr(String key, long value)
    {
        return client.decr(key, value);
    }
    
    public boolean delete(String key)
    {
        return client.delete(key);
    }
    
    @SuppressWarnings("deprecation")
    public boolean delete(String key, Date expiry)
    {
        return client.delete(key, expiry);
    }
    
    public boolean set(String key, Object value)
    {
        if (!writable)
        {
            return false;
        }
        if (value == null)
        {
            Throwable t = new Throwable("null value to cache TraceStack");
            logger.error("set a null value to memcache with key[" + key + "] ,See follow invoke trace", t);
            return false;
        }
        return client.set(key, value);
    }
    
    public boolean set(String key, Object value, Date expire)
    {
        if (!writable)
        {
            return false;
        }
        if (value == null)
        {
            Throwable t = new Throwable("null value to cache TraceStack");
            logger.error("set a null value to memcache with key[" + key + "] ,See follow invoke trace", t);
            return false;
        }
        return client.set(key, value, expire);
    }
    
    /**
     * 执行stats命令,返回缓存的当前状态
     * 
     * @return
     */
    @SuppressWarnings({"unchecked", "rawtypes"})
    public Map<String, Map<String, String>> stats()
    {
        Map map = client.stats();
        if (map == null)
        {
            return new HashMap<String, Map<String, String>>();
        }
        return map;
    }
    
    /**
     * 在所有的Memcached服务端执行缓存清除动作
     * 
     * Will return true only if succeeds in clearing all servers.
     * 
     * @return success true/false
     */
    public boolean flushAll()
    {
        return client.flushAll();
    }
    
    /**
     * 在指定的Memcached服务端执行缓存清除动作 Will return true only if succeeds in clearing all servers. If pass in null, then will
     * try to flush all servers.
     * 
     * @param servers optional array of host(s) to flush (host:port)
     * @return success true/false
     */
    public boolean flushAll(String[] servers)
    {
        return client.flushAll(servers);
    }
    
    /**
     * 进行类型转换同时处理转换异常
     * 
     * @param type
     * @param value
     * @return
     */
    private <T> T castAs(Class<T> type, String key, Object value)
    {
        if (value == null)
        {
            return null;
        }
        try
        {
            T t = type.cast(value);
            return t;
        }
        catch (ClassCastException ignoreMe)
        {
            StringBuilder errMsg = new StringBuilder("+++ incorrect cache type[");
            errMsg.append(value.getClass().getName())
                .append("] with key[" + key + "], value [")
                .append(value)
                .append("]");
            errMsg.append(",expect type [").append(type.getName()).append("]");
            logger.error(errMsg, ignoreMe);
        }
        return null;
    }

    public boolean isWritable()
    {
        return writable;
    }

    public void setWritable(boolean writable)
    {
        this.writable = writable;
    }

    public String[] getServers()
    {
        return servers;
    }
    
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,835评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,598评论 1 295
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,569评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,159评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,533评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,710评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,923评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,674评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,421评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,622评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,115评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,428评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,114评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,097评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,875评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,753评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,649评论 2 271

推荐阅读更多精彩内容